﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;

namespace Legazpi.Payroll.DataAccess.DataObjects
{
    public class PayrollSummary :EntityBase<int>
    {
        public int EmployeeId { get; set; }
        public int PayRollId { get; set; }

        public virtual Employee Employee { get; set; }
        public virtual PayrollDate PayRoll { get; set; }

        public double RegularHours { get; set; }
        public double LegalHours { get; set; }
        public double SpecialHours { get; set; }        
        public double OverTime { get; set; }
        public double OverTimeLegal { get; set; }
        public double OverTimeSpecial { get; set; }
        public double NightDiff { get; set; }
        public double NightDiffLegal { get; set; }
        public double NightDiffSpecial { get; set; }
        public double CoverUpHours { get; set; }

        [NotMapped]
        public double WorkHours 
        { 
            get 
            {
                return RegularHours +
                    LegalHours +
                    SpecialHours +
                    OverTime +
                    OverTimeLegal +
                    OverTimeSpecial +
                    NightDiff +
                    NightDiffLegal +
                    NightDiffSpecial;
            } 
        }

        #region Rates
        private Detachment employeeDetachment;
        [NotMapped]
        public Detachment EmployeeDetachment
        {
            get { return employeeDetachment ?? (employeeDetachment = Employee.Detachment); }
            set { employeeDetachment = value; }
        }
        private Client employeeClientRate;
        [NotMapped]
        public Client EmployeeClientRate
        {
            get { return employeeClientRate ?? (employeeClientRate = EmployeeDetachment != null ? EmployeeDetachment.Sector.Client : null); }
            set { employeeClientRate = value; }
        }
        
        [NotMapped]
        public double RatePerHour
        {
            get { return EmployeeDetachment != null ? EmployeeDetachment.RatePerDay : 0; }
        }
        [NotMapped]
        public double RatePerHourLegal
        {
            get { return EmployeeClientRate != null ? EmployeeClientRate.LegalHoliday / 100 : 0; }
        }
        [NotMapped]
        public double RatePerHourSpecial
        {
            get { return EmployeeClientRate != null ? EmployeeClientRate.SpecialHoliday / 100 : 0; }
        }
        [NotMapped]
        public double RatePerHourRegularOverTime
        {
            get { return EmployeeClientRate != null ? EmployeeClientRate.RegularOverTime / 100 : 0; }
        }
        [NotMapped]
        public double RatePerHourSpecialOverTime
        {
            get { return EmployeeClientRate != null ? EmployeeClientRate.SpecialOverTime / 100 : 0; }
        }
        [NotMapped]
        public double RatePerHourNightDiff
        {
            get { return EmployeeClientRate != null ? EmployeeClientRate.NightDiff / 100 : 0; }
        }
        #endregion

        #region Computations
        [NotMapped]
        public double RegularHoursPay { get { return RegularHours * RatePerHour; } }
        [NotMapped]
        public double LegalHoursPay { get { return LegalHours * RatePerHourLegal; } }
        [NotMapped]
        public double SpecialHoursPay { get { return SpecialHours * RatePerHourSpecial; } }
        [NotMapped]
        public double OverTimePay { get { return OverTime * RatePerHourRegularOverTime; } }
        [NotMapped]
        public double OverTimeLegalPay { get { return OverTimeLegal * RatePerHourLegal; } }
        [NotMapped]
        public double OverTimeSpecialPay { get { return OverTimeSpecial * RatePerHourSpecialOverTime; } }
        [NotMapped]
        public double NightDiffPay { get { return NightDiff * RatePerHourNightDiff; } }
        [NotMapped]
        public double NightDiffLegalPay { get { return NightDiffLegal * RatePerHourLegal; } }
        [NotMapped]
        public double NightDiffSpecialPay { get { return NightDiffSpecial * RatePerHourSpecial; } }
        [NotMapped]
        public double CoverUpHoursPay { get { return CoverUpHours * RatePerHour; } }
        [NotMapped]
        public double GlobalAdditional
        { 
            get 
            {                
                return PayRoll.GlobalAdjustments
                    .Where(x => x.Adjustment.IsAdditional)
                    .Sum(x => x.Amount); 
            } 
        }
        
        [NotMapped]
        public double GlobalDeduction
        {
            get
            {
                return PayRoll.GlobalAdjustments
                    .Where(x => !x.Adjustment.IsAdditional)
                    .Sum(x => x.Amount);
            }
        }
        [NotMapped]
        public double TotalDeductions
        {
            get
            {
                return GlobalDeduction + DeathContribution;
            }
        }
        [NotMapped]
        public double DeathContribution
        {
            get
            {
                return PayRoll.Contributions.Sum(x => x.Amount);
            }
        }
        [NotMapped]
        public double WorkHoursPay
        {
            get
            {
                return RegularHoursPay +
                    LegalHoursPay +
                    SpecialHoursPay +
                    OverTimePay +
                    OverTimeLegalPay +
                    OverTimeSpecialPay +
                    NightDiffPay +
                    NightDiffLegalPay +
                    NightDiffSpecialPay;
            }
        }
        [NotMapped]
        public double GrossPay
        {
            get
            {
                return WorkHoursPay +
                    GlobalAdditional +
                    CoverUpHoursPay;
            }
        }

        [NotMapped]
        public double NetPay
        {
            get
            {
                return GrossPay - TotalDeductions;
            }
        }

        #endregion
    }
}
